package main

import (
	"fmt"
)

func main() {
	/*
		指针：
		获取变量的地址 -> 指针
		&var
	*/
	var intVariable int = 100
	fmt.Printf("intVariable的值=%d, 地址=%v\n", intVariable, &intVariable)
	// intVariable的值=100, 地址=0xc000018090

	// 定义指针
	var pointerVariable *int = &intVariable
	fmt.Printf("pointerVariable=%v, 地址=%v\n", pointerVariable, &pointerVariable)
	// pointerVariable=0xc000018090, 地址=0xc00000e030
	// 指针本身也有自己的地址，所以地址能够打印出来

	// 分析
	/*
		变量名				变量值			地址
		intVariable	   	   100			  0xc000018090
		pointerVariable    0xc000018090   0xc00000e030
	*/

	i, j := 42, 2701

	p := &i         // 指向 i
	fmt.Println(*p) // 通过指针读取 i 的值
	*p = 21         // 通过指针设置 i 的值
	fmt.Println(i)  // 查看 i 的值

	p = &j         // 指向 j
	*p = *p / 37   // 通过指针对 j 进行除法运算
	fmt.Println(j) // 查看 j 的值

	// 通过指针改变变量的值
	fmt.Printf("修改之前的值=%d\n", intVariable) // 修改之前的值=100
	*pointerVariable = 200
	fmt.Printf("修改之后的值=%d\n", intVariable) // 修改之后的值=200

	var intVariable2 int = 123
	var pointerVariable2 *int = &intVariable2

	// 通过指针形式打印变量的值
	fmt.Println(*pointerVariable2)
	// 不能直接将变量赋值
	// pointerVariable2 = intVariable2
	// cannot use intVariable2 (variable of type int) as *int value in assignment
	/*
		值类型：整型，浮点型，bool，array，string —— 栈中分配
		引用类型：指针，slice，map，chan，interface —— 堆中分配
	*/
	// 出于安全性考虑，没有将指针运算加入到 go 中
	// go 中的指针更像是 java 中的引用
	// 通过指针操作，对内存消耗会非常的少，通过指针操作数据，能够很好的提升系统的性能
	// 指针可以指向另一个指针，但是不推荐这样使用

	// 没有给指针分配内容时（默认指针）值为 0, 因为为 int
	var nilPointer *int
	fmt.Printf("未分配内容的指针=%d", nilPointer)
	// 未分配内容的指针=0

	// 并且不能直接分配值
	// *nilPointer = 100
	fmt.Printf("未分配内容的指针=%d", nilPointer)
	// panic: runtime error: invalid memory address or nil pointer dereference
}
